<!DOCTYPE html>
<html lang="zh-CN">
<head>
  <meta charset="utf-8">
  <meta content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=0" name="viewport">
  
  <title>Java集合框架 | conor_hua</title>
  <meta name="description" content="辉夜大小姐想让我写博客。" />
  <meta name="keywords" content="Java,Sakura,spring" />
  
    <link rel="shortcut icon" href="https://cdn.jsdelivr.net/gh/conorhua/asset/ima/favicon00.ico">
  
  <meta http-equiv="x-dns-prefetch-control" content="on">
  <!--自定义看板娘-->
  <script src="https://cdn.jsdelivr.net/npm/jquery/dist/jquery.min.js"></script>
  <script src="/live2d-widget/autoload.js"></script>
  <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/font-awesome/css/font-awesome.min.css"/>

  <link rel="stylesheet" href="https://cdn.jsdelivr.net/gh/xbclub/staticCDN@0.6/css/googlefont.css" media="all">
<!--  <link rel="dns-prefetch" href="//cdn.jsdelivr.net">-->
  <link rel="stylesheet" id="saukra_css-css" href="https://cdn.jsdelivr.net/gh/xbclub/staticCDN@0.6/css/style.css" type="text/css" media="all">
  <link rel="stylesheet" href="https://cdn.jsdelivr.net/gh/xbclub/staticCDN@0.6/css/lib.min.css" media="all">
  <link rel="stylesheet" href="https://cdn.jsdelivr.net/gh/xbclub/staticCDN@0.6/css/font.css" media="all">
  <link rel="stylesheet" href="https://cdn.jsdelivr.net/gh/xbclub/staticCDN@0.6/css/insight.css" media="all">
  <link rel="stylesheet" href="https://cdn.jsdelivr.net/gh/xbclub/staticCDN@0.6/css/jquery.fancybox.min.css" media="all">
  <link rel="stylesheet" href="https://cdn.jsdelivr.net/gh/xbclub/staticCDN@0.6/css/zoom.css" media="all">
  <link rel="stylesheet" type="text/css" href="https://cdn.jsdelivr.net/gh/xbclub/staticCDN@0.6/css/sharejs.css">
  <link rel="stylesheet" href="/css/tags.css" media="all">
  <!--   <link rel="stylesheet" id="saukra_css-css" href="https://2heng.xin/wp-content/cache/autoptimize/css/autoptimize_ad42a61f4c7d4bdd9f91afcff6b5dda5.css
" type="text/css" media="all"> -->
  <script>
  /*Initial Variables*/
  var mashiro_option = new Object();
  var mashiro_global = new Object();
  mashiro_option.NProgressON = true;
  /* 
   * 邮箱信息之类的东西可以填在这里，这些js变量基本都作用于sakura-app.js
   * 这样的设置仅是为了方便在基于PHP开发的主题中设置js变量，既然移植到了Node上，我想或许可以精简这一逻辑吧
   */
  mashiro_option.email_domain = "";
  mashiro_option.email_name = "";
  mashiro_option.cookie_version_control = "";
  mashiro_option.qzone_autocomplete = false;
  mashiro_option.site_name = "Conor_hua";
  mashiro_option.author_name = "";
  mashiro_option.site_url = "https://conor_hua.gitee.io";
  mashiro_option.v_appId = "GyC3NzMvd0hT9Yyd2hYIC0MN-gzGzoHsz";
  mashiro_option.v_appKey = "mgOpfzbkHYqU92CV4IDlAUHQ";
  mashiro_option.mathjax = "0";
  mashiro_option.qq_api_url = "https://api.mashiro.top/qqinfo/"; 
  mashiro_option.qq_avatar_api_url = "https://api.mashiro.top/qqinfo/";

  // mashiro_option.jsdelivr_css_src = "https://cdn.jsdelivr.net/gh/moezx/cdn@3.4.5/css/lib.min.css";
  // mashiro_option.float_player_on = true;

  /*End of Initial Variables*/
  </script>
  <script type="text/javascript">
  var bg = "https://cdn.jsdelivr.net/gh/conorhua/asset/ima/banner/6f005cbc1865ff1b706aba57347988ab.webp,https://cdn.jsdelivr.net/gh/conorhua/asset/ima/banner/ox83gp.jpg,https://cdn.jsdelivr.net/gh/conorhua/asset/ima/banner/a5fa4f9db760f58fc48f03d66b4967f7.webp,https://cdn.jsdelivr.net/gh/conorhua/asset/ima/banner/zm3vey.jpg,https://cdn.jsdelivr.net/gh/conorhua/asset/ima/banner/b3e8dae89b950b940dc0edd1e8cc0566.webp,https://cdn.jsdelivr.net/gh/conorhua/asset/ima/banner/j58y6y.jpg,https://cdn.jsdelivr.net/gh/conorhua/asset/ima/banner/4217z9.jpg,https://cdn.jsdelivr.net/gh/conorhua/asset/ima/banner/j5zg2p.jpg".split(",");
  var bgindex = Math.floor(Math.random()*bg.length);
  if (!!window.ActiveXObject || "ActiveXObject" in window) { //is IE?
    alert('朋友，IE浏览器未适配哦~');
  }
  </script>
  <style type="text/css">
  .hljs-ln{border-collapse:collapse}.hljs-ln td{padding:0}.hljs-ln-n:before{content:attr(data-line-number)}
  </style>
  <style type="text/css">.site-top .lower nav{display:block !important;}.author-profile i,.post-like a,.post-share .show-share,.sub-text,.we-info a,span.sitename,.post-more i:hover,#pagination a:hover,.post-content a:hover,.float-content i:hover{color:#FE9600}.feature i,.download,.navigator i:hover,.links ul li:before,.ar-time i,span.ar-circle,.object,.comment .comment-reply-link,.siren-checkbox-radio:checked + .siren-checkbox-radioInput:after{background:#FE9600}::-webkit-scrollbar-thumb{background:#FE9600}.download,.navigator i:hover,.link-title,.links ul li:hover,#pagination a:hover,.comment-respond input[type='submit']:hover{border-color:#FE9600}.entry-content a:hover,.site-info a:hover,.comment h4 a,#comments-navi a.prev,#comments-navi a.next,.comment h4 a:hover,.site-top ul li a:hover,.entry-title a:hover,#archives-temp h3,span.page-numbers.current,.sorry li a:hover,.site-title a:hover,i.iconfont.js-toggle-search.iconsearch:hover,.comment-respond input[type='submit']:hover{color:#FE9600}.comments .comments-main{display:block !important;}.comments .comments-hidden{display:none !important;}background-position:center center;background-attachment:inherit;}
  </style>
<script src="https://cdn.jsdelivr.net/gh/conorhua/asset/js/hititle.js"></script>
<meta name="generator" content="Hexo 4.2.1"></head>

<body class="page-template page-template-user page-template-page-analytics page-template-userpage-analytics-php page page-id-1297 chinese-font serif isWebKit">
  <div class="scrollbar" id="bar">
  </div>
  <a href="#" class="cd-top faa-float animated"></a>
  <section id="main-container">
    <div class="headertop filter-dot">
  <div id="banner_wave_1"></div>
  <div id="banner_wave_2"></div>
  <figure id="centerbg" class="centerbg">
    <div class="focusinfo no-select">
      <div class="header-tou">
        <a href="https://conor_hua.gitee.io" target="_blank" rel="noopener">
          <img src="https://cdn.jsdelivr.net/gh/conorhua/asset/ima/xiaomai.jpg">
        </a>
      </div>
      <div class="header-info">
        <p id="jinrishici-sentence">正在加载今日诗词....</p>
        <script src="https://sdk.jinrishici.com/v2/browser/jinrishici.js" charset="utf-8"></script>
        <div class="top-social_v2">
          <li id="bg-pre">
            <img class="flipx" src="https://cdn.jsdelivr.net/gh/honjun/cdn@1.6/img/other/next-b.svg">
          </li>
          
          
          
          <li>
            <a href="http://mail.qq.com/cgi-bin/qm_share?t=qm_mailme&amp;email=1_bi5eLm4_Tj4uGXpqb5tLi6" target="_blank" class="social-github" title="email">
              <img src="https://cdn.jsdelivr.net/gh/conorhua/asset/ima/email.png">
            </a>
          </li>
          
          
          
          <li class="wechat">
            <a href="/#">
              <img src="https://cdn.jsdelivr.net/gh/conorhua/asset/ima/wechat.png">
            </a>
            <div class="wechatInner">
              <img src="https://cdn.jsdelivr.net/gh/conorhua/asset/ima/1.jpg">
            </div>
          </li>
          
          
          
          <li id="bg-next">
            <img src="https://cdn.jsdelivr.net/gh/honjun/cdn@1.6/img/other/next-b.svg">
          </li>
        </div>
      </div>
    </div>
  </figure>
  
  <div id="video-container" style="display: none;">
    <video style="object-fit: fill" id="bgvideo" class="video" video-name="" src="" width="auto" preload="auto">
    </video>
    <div id="video-btn" class="loadvideo videolive">
    </div>
    <div id="video-add">
    </div>
    <div class="video-stu">
    </div>
  </div>
  
  <div class="headertop-down faa-float animated" onclick="headertop_down()">
    <span>
      <i class="fa fa-chevron-down" aria-hidden="true">
      </i>
    </span>
  </div>
</div>
    <div id="page" class="site wrapper">
      <header class="site-header no-select gizle sabit" role="banner">
 
  <div class="site-top">
    <div class="site-branding">
      <span class="site-title">
        <span class="logolink moe-mashiro">
          <a href="/">
            <span class="sakurasono">Conor_hua</span>
            <span class="shironeko"></span>
          </a>
        </span>
      </span>
    </div>
    <div class="searchbox search-form-submit">
      <i class="iconfont js-toggle-search iconsearch icon-search">
      </i>
    </div>
    <div id="show-nav" class="showNav mobile-fit">
      <div class="line line1">
      </div>
      <div class="line line2">
      </div>
      <div class="line line3">
      </div>
    </div>
    <div class="lower-cantiner">
      <div class="lower">
        <nav class="mobile-fit-control hide">
          <ul id="menu-new" class="menu">
            
              <li>
                <a href="/">
                  <span class="faa-parent animated-hover">
                    <i class="fa  fa-fort-awesome faa-shake" aria-hidden="true"></i>
                    首页
                  </span>
                </a>
                
              </li>
            
              <li>
                <a href="/archives">
                  <span class="faa-parent animated-hover">
                    <i class="fa  fa-archive faa-shake" aria-hidden="true"></i>
                    归档
                  </span>
                </a>
                
                  <ul class="sub-menu">
                    
                      <li>
                        <a href="/categories/%E6%8A%80%E6%9C%AF/">
                          <i class="fa fa-code" aria-hidden="true"></i>
                          技术
                        </a>
                      </li>
                    
                      <li>
                        <a href="/categories/%E5%B9%B2%E8%B4%A7/">
                          <i class="fa fa-plug" aria-hidden="true"></i>
                          干货
                        </a>
                      </li>
                    
                  </ul>
                
              </li>
            
              <li>
                <a href="javascript:;">
                  <span class="faa-parent animated-hover">
                    <i class="fa  fa-list-ul faa-vertical" aria-hidden="true"></i>
                    清单
                  </span>
                </a>
                
                  <ul class="sub-menu">
                    
                      <li>
                        <a href="/bangumis/">
                          <i class="fa fa-film faa-vertical" aria-hidden="true"></i>
                          番剧
                        </a>
                      </li>
                    
                      <li>
                        <a href="/categories/%E6%94%B6%E8%97%8F/">
                          <i class="fa fa-star" aria-hidden="true"></i>
                          收藏
                        </a>
                      </li>
                    
                  </ul>
                
              </li>
            
              <li>
                <a href="/tags/">
                  <span class="faa-parent animated-hover">
                    <i class="fa  fa-tags" aria-hidden="true"></i>
                    标签
                  </span>
                </a>
                
              </li>
            
              <li>
                <a href="javascript:;">
                  <span class="faa-parent animated-hover">
                    <i class="fa  fa-leaf faa-wrench" aria-hidden="true"></i>
                    关于
                  </span>
                </a>
                
                  <ul class="sub-menu">
                    
                      <li>
                        <a href="/about/">
                          <i class="fa fa-meetup" aria-hidden="true"></i>
                          我？
                        </a>
                      </li>
                    
                      <li>
                        <a href="/theme-sakura/">
                          <i class="fa iconfont icon-sakura" aria-hidden="true"></i>
                          主题
                        </a>
                      </li>
                    
                  </ul>
                
              </li>
            
              <li>
                <a href="/links/">
                  <span class="faa-parent animated-hover">
                    <i class="fa  fa-link faa-shake" aria-hidden="true"></i>
                    友人帐
                  </span>
                </a>
                
              </li>
            
          </ul>
        </nav>
      </div>
    </div>
  </div>
</header>

      <link rel="stylesheet" type="text/css" href="https://cdn.jsdelivr.net/gh/xbclub/staticCDN@0.6/css/sharejs.css">
<link rel="stylesheet" href="https://cdn.jsdelivr.net/gh/xbclub/staticCDN@0.6/css/tocbot.css">
<div class="pattern-center-blank"></div>

  <div class="pattern-center single-center">
    <!-- 有配图默认渲染第一张 -->
    <div class="pattern-attachment-img">
        <img src="https://cdn.jsdelivr.net/gh/conorhua/asset/ima/upload.gif" data-src="https://cdn.jsdelivr.net/gh/conorhua/asset/ima/banner/wallhaven-e7we1k.png" class="lazyload" onerror="imgError(this,3)" style="width: 100%; height: 100%; object-fit: cover; pointer-events: none;">
      </div>
    <header class="pattern-header single-header">
      <h1 class="entry-title">
      Java集合框架</h1>
      <p class="entry-census">
        <span>
          <a href="">
            <img src="https://cdn.jsdelivr.net/gh/conorhua/asset/ima/xiaomai.jpg">
          </a>
        </span>
        <span>
          <a href="">Conor_hua</a>
        </span>
        <span class="bull">
        ·</span>
        2021-5-5
        
      
        ·<span id="readcount"></span>次阅读
      
      </p>
    </header>
  </div>

<div id="content" class="site-content">
  <div id="primary" class="content-area">
    <main id="main" class="site-main" role="main">
      <article id="post-1" class="post-1 post type-post status-publish format-standard has-post-thumbnail hentry category-uncategorized">
        <div class="toc"></div>
        <!--<div class="toc-entry-content"> <!-- 套嵌目录使用（主要为了支援评论）-->
        
        <div class="entry-content">
          <p>本博客是JVM学习的笔记。主要是记录方便日后回档。</p>
<p>本文参考视频如下：</p>
<p><a href="https://www.oracle.com/cn/java/technologies/java-se-api-doc.html" target="_blank" rel="noopener">api文档</a></p>
<p><a href="https://www.bilibili.com/video/BV1YA411T76k?p=7&spm_id_from=pageDriver" target="_blank" rel="noopener">b站集合视频</a></p>
<h1 id="集合框架"><a href="#集合框架" class="headerlink" title="集合框架"></a>集合框架</h1><p>集合主要分为Collection(单列集合)和Map(多列集合)</p>
<p>​    collection主要框架:</p>
<p><img src="https://cdn.jsdelivr.net/gh/conorhua/asset/ima/blog/collection/collection.png" alt="collection"></p>
<p>​    map主要框架：</p>
<p><img src="https://cdn.jsdelivr.net/gh/conorhua/asset/ima/blog/collection/map.png" alt="map"></p>
<h1 id="Collection"><a href="#Collection" class="headerlink" title="Collection"></a>Collection</h1><p>主要方法：</p>
<ul>
<li>add：添加单个元素</li>
<li>remove：删除指定元素</li>
<li>contains：查找元素是否存在</li>
<li>size：获取元素个数</li>
<li>isEmpty：判断集合是否为空</li>
<li>clear：清空集合</li>
<li>addAll：添加多个元素</li>
<li>containsAll：查找多个元素是否存在</li>
<li>removeAll：删除多个元素</li>
</ul>
<p>​    </p>
<h2 id="遍历方式"><a href="#遍历方式" class="headerlink" title="遍历方式"></a>遍历方式</h2><p>Iterator</p>
<p>collection的父接口Iterable中定义的接口</p>
<p>Iterator本身不存放对象，仅用以遍历集合。</p>
<pre><code class="java">Iterator iterator=list.iterator();
        while(iterator.hasNext()){
            Object next = iterator.next();
            //xxxxxxxxx
        }</code></pre>
<hr>
<p>for-each循环：</p>
<pre><code class="java">for (Object o :list) {
            ///
        }</code></pre>
<p>底层基于Iterator</p>
<hr>
<p>普通for循环</p>
<p>​        具有索引的实现子类才可以使用普通for循环遍历，否则不可。如HashSet存放的元素没有索引，不可以使用 hashset[ i ] 访问元素，故不可以使用for循环遍历。</p>
<h2 id="List"><a href="#List" class="headerlink" title="List"></a>List</h2><p>继承Collection接口</p>
<ul>
<li>list集合中元素有序（即添加顺序与取出顺序一致），且可重复</li>
<li>list集合中有索引( 可随机访问 list[i] )，索引从0开始</li>
</ul>
<p>主要方法：</p>
<ul>
<li>add（index，object）：在index位置插入object</li>
<li>addAll（index，collection）：在index位置插入多个元素</li>
<li>get（index）：获取index位置的元素</li>
<li>indexOf（object）获取object首次出现的位置</li>
<li>lastIndexOf（object）：获取object最后出现的位置</li>
<li>remove(index)：移除index位置的元素</li>
<li>set(index，object)：替换指定位置的元素 (不可以作add使用，index不存在会IndexOutOfBoundsException)</li>
<li>subList（index1，index2）：返回index1到index2的子集合(不包含index2位置)</li>
</ul>
<h3 id="ArrayList"><a href="#ArrayList" class="headerlink" title="ArrayList"></a>ArrayList</h3><p>ArrayList 可以存放任意对象，也可以存放null，本身基于数组实现，与Vector相似。</p>
<p>ArrayList效率高，线程不安全的，多线程情况下不建议使用。可通过Collections.synchronizedList()实现线程安全</p>
<h4 id="扩容机制-ArrayList"><a href="#扩容机制-ArrayList" class="headerlink" title="扩容机制-ArrayList"></a>扩容机制-ArrayList</h4><p>ArrayList底层维护了一个Object类型的数组elementData，</p>
<ul>
<li>使用无参构造器时，初始elementData容量为0，第一次扩容 grow()时容量为10，以后每次扩容1.5倍</li>
<li>如果使用指定大小的扩容器，初始大小为指定大小，以后每次扩容为1.5倍</li>
</ul>
<p>add方法：</p>
<pre><code class="java">public boolean add(E e) {
        ensureCapacityInternal(size + 1);  // Increments modCount!!
        elementData[size++] = e;
        return true;
    }</code></pre>
<p>是否需要扩容</p>
<pre><code class="java"> private void ensureCapacityInternal(int minCapacity) {
        ensureExplicitCapacity(calculateCapacity(elementData, minCapacity));
    }</code></pre>
<p>计算 最小扩容量，如果elementData为空数组，则长度返回10，否则为size + 1</p>
<pre><code class="java">private static int calculateCapacity(Object[] elementData, int minCapacity) {
        if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {
            return Math.max(DEFAULT_CAPACITY, minCapacity);
        }
        return minCapacity;
    }</code></pre>
<p>判断是否需要扩容 </p>
<pre><code class="java">private void ensureExplicitCapacity(int minCapacity) {
    modCount++; //修改数据结构的次数

    // overflow-conscious code
    //如果最小容量比数组的长度还大 则需要扩容
    if (minCapacity - elementData.length &gt; 0)
        grow(minCapacity);
}</code></pre>
<p>ArrayList 扩容的核心方法</p>
<pre><code class="java">private void grow(int minCapacity) {
        // overflow-conscious code
        int oldCapacity = elementData.length;
        int newCapacity = oldCapacity + (oldCapacity &gt;&gt; 1); //扩容算法 1.5倍
        if (newCapacity - minCapacity &lt; 0) //第一次扩容
            newCapacity = minCapacity;
        if (newCapacity - MAX_ARRAY_SIZE &gt; 0)// 新容量是否超出了ArrayList 所定义的最大容量
            newCapacity = hugeCapacity(minCapacity);
        // minCapacity is usually close to size, so this is a win:
        elementData = Arrays.copyOf(elementData, newCapacity); //使用Arrays.copyOf扩容
    }</code></pre>
<h3 id="LinkedList"><a href="#LinkedList" class="headerlink" title="LinkedList"></a>LinkedList</h3><p>实现了双向链表和双端队列的特点。</p>
<p>可以存放任意对象，包括null</p>
<p>线程不安全。</p>
<p>底层维护的是一个双向链表：</p>
<ul>
<li><p>维护了属性first和last分别指向首节点和尾节点</p>
</li>
<li><p>每个节点对象（Node）中维护了prev，next，item三个属性 </p>
</li>
<li><p>增删查改就是在维护底层的双向链表</p>
</li>
</ul>
<h3 id="ArrayList与LinkedList"><a href="#ArrayList与LinkedList" class="headerlink" title="ArrayList与LinkedList"></a>ArrayList与LinkedList</h3><ul>
<li>ArrayList底层是数组，LinkedList底层是双向链表</li>
<li>ArrayList增删效率低，扩容数组有消耗，改查效率高</li>
<li>LinkedList增删效率高，改查效率低</li>
<li>都是线程不安全的</li>
</ul>
<p>如何选择：</p>
<ul>
<li>如果改查的操作多，选择ArrayList</li>
<li>如果增删的操作多，选择LinkedList</li>
<li>一般来说，大部分操作都是查询，因此大部分情况选择ArrayList</li>
<li>根据业务灵活选择：在一个项目中，可以一个模块使用ArrayList，另一个模块使用LinkedList。</li>
</ul>
<h2 id="Set"><a href="#Set" class="headerlink" title="Set"></a>Set</h2><ul>
<li>无序（添加和取出顺序不一致），没有索引</li>
<li>不允许重复，最多一个null</li>
</ul>
<h3 id="HashSet"><a href="#HashSet" class="headerlink" title="HashSet"></a>HashSet</h3><ul>
<li>底层是HashMap  ，维护一个hash表， 内部有一个static final 的哨兵属性 PRESENT = new Object()； 无意义 仅做占位 供HashMap的value占位。</li>
</ul>
<p>public HashSet(){</p>
<p>​        map=new HashMap&lt;&gt;()；</p>
<p>}</p>
<ul>
<li>调用add方法时，先得到hash值，然后转换为table的索引</li>
<li>查看table的索引位置是否有元素，如果没有，直接加入；如果有，则调用equals方法比较，如果相同则返回，如果不同，则向后比较，直到添加到链表末尾。</li>
</ul>
<h4 id="扩容机制-HashSet"><a href="#扩容机制-HashSet" class="headerlink" title="扩容机制-HashSet"></a>扩容机制-HashSet</h4><ul>
<li>底层是HashMap ，扩容就是扩容table。</li>
<li>在Java8中，如果链表的元素个数超过TREEIFY_THRESHOLD( 默认8 )，且table的大小 &gt;=MIN-TREEIFY_CAPACITY( 默认64 )就会进行树化 （ 红黑树 ），否则继续扩容table</li>
<li>如果table==null 或者table.length==0，会进行第一次扩容 resize()，默认talbe扩容为16大小，以后每次扩容到原来的2倍</li>
<li>size属性到达临界值 （table.length*LOAD_FACTOR 0.75） 则会扩容</li>
<li>单条链表长度到达8 且table.length &lt; 64也会扩容</li>
</ul>
<h5 id="add方法"><a href="#add方法" class="headerlink" title="add方法"></a>add方法</h5><pre><code class="java">public boolean add(E e) {
        return map.put(e, PRESENT)==null;
    }


public V put(K key, V value) {
        return putVal(hash(key), key, value, false, true);
    }</code></pre>
<h5 id="得到hash值"><a href="#得到hash值" class="headerlink" title="得到hash值"></a>得到hash值</h5><pre><code class="java">static final int hash(Object key) {
        int h;
        return (key == null) ? 0 : (h = key.hashCode()) ^ (h &gt;&gt;&gt; 16);
    //无符号右移16位，目的是为了减少hash冲突
    }</code></pre>
<h5 id="putVal方法"><a href="#putVal方法" class="headerlink" title="putVal方法"></a>putVal方法</h5><pre><code class="java"> final V putVal(int hash, K key, V value, boolean onlyIfAbsent,
                   boolean evict) {
        Node&lt;K,V&gt;[] tab; Node&lt;K,V&gt; p; int n, i; //辅助变量
        if ((tab = table) == null || (n = tab.length) == 0)
            //第一次扩容 resize()
            n = (tab = resize()).length;

          //得到hash对应table的索引  i = (n - 1) &amp; hash 取模
          //如果p == null 则说明table[i]出为空直接新建Node存放
          //如果p！=null 
        if ((p = tab[i = (n - 1) &amp; hash]) == null)
            //创建Node 存放数据  key才是真实数据 value 是哨兵
            tab[i] = newNode(hash, key, value, null);
        else {
            Node&lt;K,V&gt; e; K k;
            //判断hash值一样并且 地址一样 或者 equal方法一样 就说明是重复元素
            if (p.hash == hash &amp;&amp;
                ((k = p.key) == key || (key != null &amp;&amp; key.equals(k))))
                e = p;
            //判断是否是红黑树
            //如果是则 按调用putTreeVal判断
            else if (p instanceof TreeNode)
                e = ((TreeNode&lt;K,V&gt;)p).putTreeVal(this, tab, hash, key, value);
            else {
                //判断链表节点和新增节点是否相同
                for (int binCount = 0; ; ++binCount) {
                    //下一节点为null 则加入到尾端
                    if ((e = p.next) == null) {
                        p.next = newNode(hash, key, value, null);
                        //判断链表长度是否&gt;=TREEIFY_THRESHOLD 8 
                        //如果大于 则调用 treeifyBin 对当前链表 尝试树化
                        if (binCount &gt;= TREEIFY_THRESHOLD - 1) // -1 for 1st
                            treeifyBin(tab, hash);
                        break;
                    }
                    //一直比较和下一个节点是否相同
                    if (e.hash == hash &amp;&amp;
                        ((k = e.key) == key || (key != null &amp;&amp; key.equals(k))))
                        break;
                    p = e;
                }
            }
            //存在重复元素
            if (e != null) { // existing mapping for key
                V oldValue = e.value;
                if (!onlyIfAbsent || oldValue == null)
                    //替换value，不替换key 所以HashSet存入相同元素不替换
                    e.value = value;
                afterNodeAccess(e);  //HashMap中保留的空方法，此处可忽略
                return oldValue;
            }
        }
        ++modCount;//修改次数++
        if (++size &gt; threshold) //超过缓冲值，则扩容
            resize();
        afterNodeInsertion(evict); //HashMap中保留的空方法，此处可忽略
        return null; //返回null 说明添加成功
    }</code></pre>
<h5 id="resize方法-扩容核心"><a href="#resize方法-扩容核心" class="headerlink" title="resize方法 扩容核心"></a>resize方法 扩容核心</h5><pre><code class="java">final Node&lt;K,V&gt;[] resize() {
        Node&lt;K,V&gt;[] oldTab = table;
        int oldCap = (oldTab == null) ? 0 : oldTab.length;
        int oldThr = threshold;
        int newCap, newThr = 0;
        if (oldCap &gt; 0) {
            if (oldCap &gt;= MAXIMUM_CAPACITY) {
                threshold = Integer.MAX_VALUE;
                return oldTab;
            }
            //扩容newCap = oldCap &lt;&lt; 1  两倍
            else if ((newCap = oldCap &lt;&lt; 1) &lt; MAXIMUM_CAPACITY &amp;&amp;
                     oldCap &gt;= DEFAULT_INITIAL_CAPACITY)
                newThr = oldThr &lt;&lt; 1; // double threshold
        }
        else if (oldThr &gt; 0) // initial capacity was placed in threshold
            newCap = oldThr;
        else {               // zero initial threshold signifies using defaults
            newCap = DEFAULT_INITIAL_CAPACITY;//第一次默认16
            newThr = (int)(DEFAULT_LOAD_FACTOR * DEFAULT_INITIAL_CAPACITY);
            //缓冲  DEFAULT_LOAD_FACTOR 0.75 * DEFAULT_INITIAL_CAPACITY 16  = 12
            //减少hash冲突几率
            //DEFAULT_LOAD_FACTOR 0.75 加载因子 LOAD_FACTOR
        }
        //新的缓冲值为0 就newCap * loadFactor
        if (newThr == 0) {
            float ft = (float)newCap * loadFactor;
            newThr = (newCap &lt; MAXIMUM_CAPACITY &amp;&amp; ft &lt; (float)MAXIMUM_CAPACITY ?
                      (int)ft : Integer.MAX_VALUE);
        }
        threshold = newThr;
        @SuppressWarnings({&quot;rawtypes&quot;,&quot;unchecked&quot;})
        //开辟空间！！！
        Node&lt;K,V&gt;[] newTab = (Node&lt;K,V&gt;[])new Node[newCap];
        table = newTab;
        if (oldTab != null) {
            for (int j = 0; j &lt; oldCap; ++j) {
                Node&lt;K,V&gt; e;
                if ((e = oldTab[j]) != null) {
                    oldTab[j] = null;
                    if (e.next == null)
                        newTab[e.hash &amp; (newCap - 1)] = e;
                    else if (e instanceof TreeNode)
                        ((TreeNode&lt;K,V&gt;)e).split(this, newTab, j, oldCap);
                    else { // preserve order
                        Node&lt;K,V&gt; loHead = null, loTail = null;
                        Node&lt;K,V&gt; hiHead = null, hiTail = null;
                        Node&lt;K,V&gt; next;
                        do {
                            next = e.next;
                            if ((e.hash &amp; oldCap) == 0) {
                                if (loTail == null)
                                    loHead = e;
                                else
                                    loTail.next = e;
                                loTail = e;
                            }
                            else {
                                if (hiTail == null)
                                    hiHead = e;
                                else
                                    hiTail.next = e;
                                hiTail = e;
                            }
                        } while ((e = next) != null);
                        if (loTail != null) {
                            loTail.next = null;
                            newTab[j] = loHead;
                        }
                        if (hiTail != null) {
                            hiTail.next = null;
                            newTab[j + oldCap] = hiHead;
                        }
                    }
                }
            }
        }
        return newTab;
    }</code></pre>
<h5 id="树化方法-treeifyBin"><a href="#树化方法-treeifyBin" class="headerlink" title="树化方法 treeifyBin"></a>树化方法 treeifyBin</h5><pre><code class="java">final void treeifyBin(Node&lt;K,V&gt;[] tab, int hash) {
    int n, index; Node&lt;K,V&gt; e;
    //如果table的长度小于  MIN_TREEIFY_CAPACITY 64 则扩容table
    //否则 树化
    if (tab == null || (n = tab.length) &lt; MIN_TREEIFY_CAPACITY)
        resize();
    else if ((e = tab[index = (n - 1) &amp; hash]) != null) {
        TreeNode&lt;K,V&gt; hd = null, tl = null;
        do {
            TreeNode&lt;K,V&gt; p = replacementTreeNode(e, null);
            if (tl == null)
                hd = p;
            else {
                p.prev = tl;
                tl.next = p;
            }
            tl = p;
        } while ((e = e.next) != null);
        if ((tab[index] = hd) != null)
            hd.treeify(tab);
    }
}</code></pre>
<h3 id="LinkedHashSet"><a href="#LinkedHashSet" class="headerlink" title="LinkedHashSet"></a>LinkedHashSet</h3><ul>
<li><p>HashSet的子类，底层是一个LinkedHashMap，维护了一个hash表+双向链表，内部有一个static final 的哨兵属性 PRESENT = new Object()； 无意义 仅做占位 供LinkedHashMap的value占位。</p>
<pre><code class="java">public LinkedHashSet() {
    super(16, .75f, true);
}
HashSet(int initialCapacity, float loadFactor, boolean dummy) {
        map = new LinkedHashMap&lt;&gt;(initialCapacity, loadFactor);
    }</code></pre>
</li>
<li><p>根据hashCode来决定元素位置，同时用双向链表来来维护元素次序，使之看起来以插入顺序保存</p>
</li>
<li><p>不允许重复元素</p>
</li>
<li><p>调用add方法时，先得到hash值，然后求索引，确定该元素在hashTable的位置，然后将添加的元素加入到双向链表中。</p>
</li>
<li><p>根据双向链表来遍历，能确保插入顺序和遍历顺序一致。</p>
</li>
<li><p>table是HashMap$Node  存放的元素是LinkedHashMap$Entry</p>
</li>
<li><p>继承于HashSet，<strong>在HashSet的基础上维护了一个双向链表</strong></p>
</li>
</ul>
<h4 id="扩容机制-LinkedHashSet"><a href="#扩容机制-LinkedHashSet" class="headerlink" title="扩容机制-LinkedHashSet"></a>扩容机制-LinkedHashSet</h4><p>继承于HashSet，扩容机制与HashSet一致</p>
<h2 id="TreeSet"><a href="#TreeSet" class="headerlink" title="TreeSet"></a>TreeSet</h2><ul>
<li><p>底层是TreeMap</p>
</li>
<li><p>使用<code>TreeMap</code>时，放入的Key必须实现<code>Comparable</code>接口。<code>String</code>、<code>Integer</code>这些类已经实现了<code>Comparable</code>接口，因此可以直接作为Key使用。作为Value的对象则没有任何要求。</p>
<p>如果作为Key的class没有实现<code>Comparable</code>接口，那么，必须在创建<code>TreeMap</code>时同时指定一个自定义排序算法。</p>
</li>
</ul>
<h1 id="Map"><a href="#Map" class="headerlink" title="Map"></a>Map</h1><ul>
<li>存储具有映射关系的数据： Key-Value  键值对</li>
<li>Key 和 Value 可以是任意对象，封装在HashMap$Node 中</li>
<li>Key不允许重复，存入时 如有相同的Key会覆盖Value</li>
<li>key 可以为null，只能有一个；Value可以为null，多个。</li>
<li>K-V 本质是HashMap$Node</li>
<li>EntrySet&lt; Entry&lt;K,V&gt; &gt;，本质存放的是HashMap$Node的引用，方便遍历 ； 多态  HashMap$Node implement Map$Entry</li>
</ul>
<p>常用方法：</p>
<ul>
<li><p>put：添加</p>
</li>
<li><p>remove：根据key删除k-v</p>
</li>
<li><p>get：根据k获取v</p>
</li>
<li><p>size：获取元素个数</p>
</li>
<li><p>isEmpty：判断map是否为空</p>
</li>
<li><p>clear：清空</p>
</li>
<li><p>containsKey：查找key是否存在</p>
</li>
</ul>
<h2 id="遍历方式-1"><a href="#遍历方式-1" class="headerlink" title="遍历方式"></a>遍历方式</h2><ul>
<li>containsKey：查找是否有Key</li>
<li>KeySet：获得所有K</li>
<li>Values：获得所有V</li>
<li>EntrySet：获得所有K-V</li>
</ul>
<p>第一种：通过keySet取key，通过key取value  </p>
<pre><code class="java"> //for-each循环
        for (Object key :map.keySet()) {
            System.out.println(key + &quot;-&quot; + map.get(key));
        }
 //迭代器
        Iterator iterator = map.keySet().iterator();
        while (iterator.hasNext()){
            Object key = iterator.next();
            System.out.println(key + &quot;-&quot; + map.get(key));
        }</code></pre>
<p>第二种：只取value</p>
<p>​    HashMap$Node 里的values 引用存放在一个 collection里  HashMap$values</p>
<p>可以通过collection的遍历方式遍历</p>
<pre><code class="java">//for-each
        for (Object value :map.values()) {
            System.out.println(&quot;value: &quot; + value);
        }
//Iterator
        Iterator iterator = map.values().iterator();
        while (iterator.hasNext()) {
            Object value =  iterator.next();
            System.out.println(&quot;value: &quot; +value);
        }</code></pre>
<p>第三种：通过EntrySet 来取K-V</p>
<pre><code class="java"> //for-each
        for (Object o : map.entrySet()) {
            Map.Entry m= (Map.Entry) o;
            System.out.println(m.getKey() + &quot;-&quot;+ m.getValue());
        }
 //Iterator
        Iterator iterator = map.entrySet().iterator();
        while (iterator.hasNext()) {
            Object next =  iterator.next();
            Map.Entry m= (Map.Entry) next;
            System.out.println(m.getKey()+ &quot;-&quot; + m.getValue());
        }</code></pre>
<h2 id="HashMap"><a href="#HashMap" class="headerlink" title="HashMap"></a>HashMap</h2><ul>
<li>Map接口的常用实现类</li>
<li>存储K-V，HashMap$Node</li>
<li>key不能重复，value可以重复，允许一个null Key，多个value</li>
<li>存入相同元素时，不替换key 替换value</li>
<li>与HashSet(底层是HashMap)一样是线程不安全的，不保证次序的。</li>
<li>底层是hash表( 数组+链表+红黑树 jdk8 ) (数组+链表 jdk7 )</li>
<li>调用add方法时，先得到hash值，然后转换为table的索引</li>
<li>查看table的索引位置是否有元素，如果没有，直接加入；如果有，则调用equals方法比较，如果相同则覆盖，如果不同，则向后比较，直到添加到链表末尾。</li>
</ul>
<h3 id="扩容机制"><a href="#扩容机制" class="headerlink" title="扩容机制"></a>扩容机制</h3><ul>
<li>在Java8中，如果链表的元素个数超过TREEIFY_THRESHOLD( 默认8 )，且table的大小 &gt;=MIN-TREEIFY_CAPACITY( 默认64 )就会进行树化 （ 红黑树 ），否则继续扩容table</li>
<li>如果table==null 或者table.length==0，会进行第一次扩容 resize()，默认talbe扩容为16大小，以后每次扩容到原来的2倍</li>
<li>size属性到达临界值 （table.length*LOAD_FACTOR 0.75） 则会扩容</li>
<li>单条链表长度到达8 且table.length &lt; 64也会扩容</li>
</ul>
<h4 id="put方法"><a href="#put方法" class="headerlink" title="put方法"></a>put方法</h4><pre><code class="java">public V put(K key, V value) {
        return putVal(hash(key), key, value, false, true);
    }</code></pre>
<h4 id="得到hash值-1"><a href="#得到hash值-1" class="headerlink" title="得到hash值"></a>得到hash值</h4><pre><code class="java">static final int hash(Object key) {
        int h;
        return (key == null) ? 0 : (h = key.hashCode()) ^ (h &gt;&gt;&gt; 16);
    //无符号右移16位，目的是为了减少hash冲突
    }</code></pre>
<h4 id="putVal方法-1"><a href="#putVal方法-1" class="headerlink" title="putVal方法"></a>putVal方法</h4><pre><code class="java"> final V putVal(int hash, K key, V value, boolean onlyIfAbsent,
                   boolean evict) {
        Node&lt;K,V&gt;[] tab; Node&lt;K,V&gt; p; int n, i; //辅助变量
        if ((tab = table) == null || (n = tab.length) == 0)
            //第一次扩容 resize()
            n = (tab = resize()).length;

          //得到hash对应table的索引  i = (n - 1) &amp; hash 取模
          //如果p == null 则说明table[i]出为空直接新建Node存放
          //如果p！=null 
        if ((p = tab[i = (n - 1) &amp; hash]) == null)
            //创建Node 存放数据  key才是真实数据 value 是哨兵
            tab[i] = newNode(hash, key, value, null);
        else {
            Node&lt;K,V&gt; e; K k;
            //判断hash值一样并且 地址一样 或者 equal方法一样 就说明是重复元素
            if (p.hash == hash &amp;&amp;
                ((k = p.key) == key || (key != null &amp;&amp; key.equals(k))))
                e = p;
            //判断是否是红黑树
            //如果是则 按调用putTreeVal判断
            else if (p instanceof TreeNode)
                e = ((TreeNode&lt;K,V&gt;)p).putTreeVal(this, tab, hash, key, value);
            else {
                //判断链表节点和新增节点是否相同
                for (int binCount = 0; ; ++binCount) {
                    //下一节点为null 则加入到尾端
                    if ((e = p.next) == null) {
                        p.next = newNode(hash, key, value, null);
                        //判断链表长度是否&gt;=TREEIFY_THRESHOLD 8 
                        //如果大于 则调用 treeifyBin 对当前链表 尝试树化
                        if (binCount &gt;= TREEIFY_THRESHOLD - 1) // -1 for 1st
                            treeifyBin(tab, hash);
                        break;
                    }
                    //一直比较和下一个节点是否相同
                    if (e.hash == hash &amp;&amp;
                        ((k = e.key) == key || (key != null &amp;&amp; key.equals(k))))
                        break;
                    p = e;
                }
            }
            //存在重复元素
            if (e != null) { // existing mapping for key
                V oldValue = e.value;
                if (!onlyIfAbsent || oldValue == null)
                    //替换value，不替换key 所以HashSet存入相同元素不替换
                    e.value = value;
                afterNodeAccess(e); //HashMap中保留的空方法，此处可忽略
                return oldValue;
            }
        }
        ++modCount;//修改次数++
        if (++size &gt; threshold) //超过缓冲值，则扩容
            resize();
        afterNodeInsertion(evict); //HashMap中保留的空方法，此处可忽略
        return null; //返回null 说明添加成功
    }</code></pre>
<h4 id="resize方法-扩容核心-1"><a href="#resize方法-扩容核心-1" class="headerlink" title="resize方法 扩容核心"></a>resize方法 扩容核心</h4><pre><code class="java">final Node&lt;K,V&gt;[] resize() {
        Node&lt;K,V&gt;[] oldTab = table;
        int oldCap = (oldTab == null) ? 0 : oldTab.length;
        int oldThr = threshold;
        int newCap, newThr = 0;
        if (oldCap &gt; 0) {
            if (oldCap &gt;= MAXIMUM_CAPACITY) {
                threshold = Integer.MAX_VALUE;
                return oldTab;
            }
            //扩容newCap = oldCap &lt;&lt; 1  两倍
            else if ((newCap = oldCap &lt;&lt; 1) &lt; MAXIMUM_CAPACITY &amp;&amp;
                     oldCap &gt;= DEFAULT_INITIAL_CAPACITY)
                newThr = oldThr &lt;&lt; 1; // double threshold
        }
        else if (oldThr &gt; 0) // initial capacity was placed in threshold
            newCap = oldThr;
        else {               // zero initial threshold signifies using defaults
            newCap = DEFAULT_INITIAL_CAPACITY;//第一次默认16
            newThr = (int)(DEFAULT_LOAD_FACTOR * DEFAULT_INITIAL_CAPACITY);
            //缓冲  DEFAULT_LOAD_FACTOR 0.75 * DEFAULT_INITIAL_CAPACITY 16  = 12
            //减少hash冲突几率
            //DEFAULT_LOAD_FACTOR 0.75 加载因子 LOAD_FACTOR
        }
        //新的缓冲值为0 就newCap * loadFactor
        if (newThr == 0) {
            float ft = (float)newCap * loadFactor;
            newThr = (newCap &lt; MAXIMUM_CAPACITY &amp;&amp; ft &lt; (float)MAXIMUM_CAPACITY ?
                      (int)ft : Integer.MAX_VALUE);
        }
        threshold = newThr;
        @SuppressWarnings({&quot;rawtypes&quot;,&quot;unchecked&quot;})
        //开辟空间！！！
        Node&lt;K,V&gt;[] newTab = (Node&lt;K,V&gt;[])new Node[newCap];
        table = newTab;
        if (oldTab != null) {
            for (int j = 0; j &lt; oldCap; ++j) {
                Node&lt;K,V&gt; e;
                if ((e = oldTab[j]) != null) {
                    oldTab[j] = null;
                    if (e.next == null)
                        newTab[e.hash &amp; (newCap - 1)] = e;
                    else if (e instanceof TreeNode)
                        ((TreeNode&lt;K,V&gt;)e).split(this, newTab, j, oldCap);
                    else { // preserve order
                        Node&lt;K,V&gt; loHead = null, loTail = null;
                        Node&lt;K,V&gt; hiHead = null, hiTail = null;
                        Node&lt;K,V&gt; next;
                        do {
                            next = e.next;
                            if ((e.hash &amp; oldCap) == 0) {
                                if (loTail == null)
                                    loHead = e;
                                else
                                    loTail.next = e;
                                loTail = e;
                            }
                            else {
                                if (hiTail == null)
                                    hiHead = e;
                                else
                                    hiTail.next = e;
                                hiTail = e;
                            }
                        } while ((e = next) != null);
                        if (loTail != null) {
                            loTail.next = null;
                            newTab[j] = loHead;
                        }
                        if (hiTail != null) {
                            hiTail.next = null;
                            newTab[j + oldCap] = hiHead;
                        }
                    }
                }
            }
        }
        return newTab;
    }</code></pre>
<h4 id="树化方法-treeifyBin-1"><a href="#树化方法-treeifyBin-1" class="headerlink" title="树化方法 treeifyBin"></a>树化方法 treeifyBin</h4><pre><code class="java">final void treeifyBin(Node&lt;K,V&gt;[] tab, int hash) {
    int n, index; Node&lt;K,V&gt; e;
    //如果table的长度小于  MIN_TREEIFY_CAPACITY 64 则扩容table
    //否则 树化
    if (tab == null || (n = tab.length) &lt; MIN_TREEIFY_CAPACITY)
        resize();
    else if ((e = tab[index = (n - 1) &amp; hash]) != null) {
        TreeNode&lt;K,V&gt; hd = null, tl = null;
        do {
            TreeNode&lt;K,V&gt; p = replacementTreeNode(e, null);
            if (tl == null)
                hd = p;
            else {
                p.prev = tl;
                tl.next = p;
            }
            tl = p;
        } while ((e = e.next) != null);
        if ((tab[index] = hd) != null)
            hd.treeify(tab);
    }
}</code></pre>
<h2 id="HashTable"><a href="#HashTable" class="headerlink" title="HashTable"></a>HashTable</h2><p>实现了Map接口</p>
<pre><code class="java">public class Hashtable&lt;K,V&gt;
    extends Dictionary&lt;K,V&gt;
    implements Map&lt;K,V&gt;, Cloneable, java.io.Serializable</code></pre>
<ul>
<li>存放K-V</li>
<li>底层维护一个hash表 (数组+链表)  类型HashTable$Entry   初始大小为11，加载因子load_factor 0.75</li>
<li>key和value都不能为null    <font color=red>NullPointerException</font></li>
<li>用法与HashMap类似</li>
<li><strong>线程安全</strong>  synchronized</li>
</ul>
<h3 id="扩容机制-1"><a href="#扩容机制-1" class="headerlink" title="扩容机制"></a>扩容机制</h3><ul>
<li>第一次扩容大小为11 此后扩容大小为2倍+1</li>
<li>count &gt;= threshold 扩容条件</li>
</ul>
<pre><code>rehash()

int newCapacity = (oldCapacity &lt;&lt; 1) + 1;  2倍+1</code></pre><h3 id="Propertiies"><a href="#Propertiies" class="headerlink" title="Propertiies"></a>Propertiies</h3><ul>
<li>继承HashTable</li>
<li>用法与HashTable类似</li>
<li>更多用于从xxx.properties文件中，加载Properties类对象。</li>
</ul>
<h2 id="TreeMap"><a href="#TreeMap" class="headerlink" title="TreeMap"></a>TreeMap</h2><p>使用<code>TreeMap</code>时，放入的Key必须实现<code>Comparable</code>接口。<code>String</code>、<code>Integer</code>这些类已经实现了<code>Comparable</code>接口，因此可以直接作为Key使用。作为Value的对象则没有任何要求。</p>
<p>如果作为Key的class没有实现<code>Comparable</code>接口，那么，必须在创建<code>TreeMap</code>时同时指定一个自定义排序算法。</p>
<h1 id="集合的选择"><a href="#集合的选择" class="headerlink" title="集合的选择"></a>集合的选择</h1><p>在开发中，主要是依据<strong>业务需求</strong>来选择适合的集合实现类：</p>
<ol>
<li>先判断存储的类型 ( 一组对象[单列] or 一组键值对[双列] )</li>
<li>一组对象[单列]：<ul>
<li>允许重复：List<ul>
<li>增删多：LinkedList (底层维护一个双向链表)</li>
<li>查改多：ArrayList （底层维护一个数组）</li>
</ul>
</li>
<li>不允许重复：Set<ul>
<li>无序：HashSet   (底层是HashMap)</li>
<li>有序：TreeSet</li>
<li>插入顺序和取出顺序一致：LinkedHashSet  (底层是LinkedHashMap)</li>
</ul>
</li>
</ul>
</li>
<li>一组键值对：Map<ul>
<li>键值无序：HashMap (底层维护 一个数组 + 链表 + 红黑树)</li>
<li>键值排序：TreeMap</li>
<li>插入顺序和取出顺序一致：LinkedHashMap</li>
<li>读取文件：Properties</li>
</ul>
</li>
</ol>

        </div>
        <!-- .entry-content -->
        
        <p></p>
          
        <div style="text-align:center; width: 100%" class="social-share share-mobile" data-disabled="diandian, tencent"></div>
        <footer class="post-footer">
          <div class="post-lincenses"><a href="https://creativecommons.org/licenses/by-nc-sa/4.0/deed.zh" target="_blank" rel="nofollow"><i class="fa fa-creative-commons" aria-hidden="true"></i> 知识共享署名-非商业性使用-相同方式共享 4.0 国际许可协议</a></div>
          <div class="post-tags">
            <div class="tag-cloud">
              <div class="tag-cloud-title">
              </div>
              <div class="tag-cloud-tags">
              <a href="/tags/CDN/" style="font-size: 10px; color: #f38181">CDN</a> <a href="/tags/Chrome/" style="font-size: 10px; color: #f38181">Chrome</a> <a href="/tags/Collection/" style="font-size: 10px; color: #f38181">Collection</a> <a href="/tags/ElasticSearch/" style="font-size: 10px; color: #f38181">ElasticSearch</a> <a href="/tags/IO%E6%B5%81/" style="font-size: 10px; color: #f38181">IO流</a> <a href="/tags/JVM/" style="font-size: 10px; color: #f38181">JVM</a> <a href="/tags/Java/" style="font-size: 16.67px; color: #b4c1b8">Java</a> <a href="/tags/Linux/" style="font-size: 10px; color: #f38181">Linux</a> <a href="/tags/MySQL/" style="font-size: 10px; color: #f38181">MySQL</a> <a href="/tags/OIS/" style="font-size: 10px; color: #f38181">OIS</a> <a href="/tags/Redis/" style="font-size: 13.33px; color: #d4a19c">Redis</a> <a href="/tags/SQL/" style="font-size: 10px; color: #f38181">SQL</a> <a href="/tags/Springboot/" style="font-size: 10px; color: #f38181">Springboot</a> <a href="/tags/TCP-IP/" style="font-size: 10px; color: #f38181">TCP/IP</a> <a href="/tags/Tomcat/" style="font-size: 10px; color: #f38181">Tomcat</a> <a href="/tags/aop/" style="font-size: 10px; color: #f38181">aop</a> <a href="/tags/bili/" style="font-size: 10px; color: #f38181">bili</a> <a href="/tags/eclipse/" style="font-size: 10px; color: #f38181">eclipse</a> <a href="/tags/git/" style="font-size: 10px; color: #f38181">git</a> <a href="/tags/github/" style="font-size: 13.33px; color: #d4a19c">github</a> <a href="/tags/ioc/" style="font-size: 10px; color: #f38181">ioc</a> <a href="/tags/java/" style="font-size: 20px; color: #95e1d3">java</a> <a href="/tags/jsdelivr/" style="font-size: 10px; color: #f38181">jsdelivr</a> <a href="/tags/oracle/" style="font-size: 10px; color: #f38181">oracle</a> <a href="/tags/spring/" style="font-size: 13.33px; color: #d4a19c">spring</a> <a href="/tags/sring/" style="font-size: 10px; color: #f38181">sring</a> <a href="/tags/vscode/" style="font-size: 10px; color: #f38181">vscode</a> <a href="/tags/web/" style="font-size: 10px; color: #f38181">web</a> <a href="/tags/%E5%8F%8D%E5%B0%84/" style="font-size: 10px; color: #f38181">反射</a> <a href="/tags/%E5%A4%9A%E7%BA%BF%E7%A8%8B/" style="font-size: 10px; color: #f38181">多线程</a> <a href="/tags/%E5%AE%9E%E4%B9%A0/" style="font-size: 10px; color: #f38181">实习</a> <a href="/tags/%E6%8E%92%E5%BA%8F/" style="font-size: 10px; color: #f38181">排序</a> <a href="/tags/%E6%B3%A8%E8%A7%A3/" style="font-size: 10px; color: #f38181">注解</a> <a href="/tags/%E6%B4%BE%E5%A4%A7%E6%98%9F/" style="font-size: 10px; color: #f38181">派大星</a> <a href="/tags/%E7%BD%91%E7%BB%9C/" style="font-size: 10px; color: #f38181">网络</a>
              </div>
            </div>
          </div>
          <div class="post-share">
            <div class="social-share sharehidden share-component"></div>
            <i class="iconfont show-share icon-forward"></i>
          </div>
        </footer><!-- .entry-footer -->
      </article>
      <!-- #post-## -->
      <div class="toc" style="background: none;"></div>
      <section class="post-squares nextprev">
        
          
            <div class="post-nepre half previous">
          
            <a href="/posts/29d8a02c.html" rel="prev">
              <div class="background">
<!--                <img class="lazyload" src="https://cdn.jsdelivr.net/gh/conorhua/asset/ima/upload.gif" data-src="https://cdn.jsdelivr.net/gh/conorhua/asset/ima/banner/wallhaven-wyzxkr.jpg" style="width: 100%; height: 100%; object-fit: cover; pointer-events: none;" onerror="imgError(this,3)" src="https://cdn.jsdelivr.net/gh/conorhua/asset/ima/banner/wallhaven-wyzxkr.jpg">-->
                
                <img class="lazyload" src="https://cdn.jsdelivr.net/gh/conorhua/asset/ima/upload.gif" data-src="https://cdn.jsdelivr.net/gh/conorhua/asset/ima/banner/wallhaven-wyzxkr.jpg" style="width: 100%; height: 100%; object-fit: cover; pointer-events: none;" onerror="imgError(this,3)" >
              </div>
              <span class="label">
              Previous Post</span>
              <div class="info">
                <h3>
                Springboot小白记录(一)</h3>
                <hr>
              </div>
            </a>
          </div>
        
        
          
            <div class="post-nepre half next">
          
            <a href="/posts/c51233f6.html" rel="next">
              <div class="background">
                
                <img class="lazyload" src="https://cdn.jsdelivr.net/gh/conorhua/asset/ima/upload.gif" data-src="https://cdn.jsdelivr.net/gh/conorhua/asset/ima/banner/wallhaven-m9wv21.png" style="width: 100%; height: 100%; object-fit: cover; pointer-events: none;" onerror="imgError(this,3)" >
              </div>
              <span class="label">
              Next Post</span>
              <div class="info">
                <h3>
                JavaIO流</h3>
                <hr>
              </div>
            </a>
          </div>
        
      </section>
      
      <section class="author-profile">
        <div class="info" itemprop="author" itemscope="" itemtype="https://schema.org/Person">
          <a href="" class="profile gravatar"><img src="https://cdn.jsdelivr.net/gh/conorhua/asset/ima/xiaomai.jpg" itemprop="image" alt="Conor_hua" height="70" width="70"></a>
          <div class="meta">
            <span class="title">Author</span>
            <h3 itemprop="name">
            <a href="" itemprop="url" rel="author">Conor_hua</a>
            </h3>
          </div>
        </div>
        <hr>
        <p><i class="iconfont icon-write"></i></p>
      </section>
    </main><!-- #main -->
  </div><!-- #primary -->
</div>


    </div>    
    <div class="ins-search">
    <div class="ins-search-mask"></div>
    <div class="ins-search-container">
        <div class="ins-input-wrapper">
            <input type="text" class="ins-search-input" placeholder="请输入关键词..."/>
            <span class="ins-close ins-selectable"><i class="fa fa-times-circle"></i></span>
        </div>
        <div class="ins-section-wrapper">
            <div class="ins-section-container"></div>
        </div>
    </div>
</div>
<script>
(function (window) {
    var INSIGHT_CONFIG = {
        TRANSLATION: {
            POSTS: '文章',
            // PAGES: '页面',
            CATEGORIES: '分类',
            TAGS: '标签',
        },
        ROOT_URL: '/',
        CONTENT_URL: '/content.json',
    };
    window.INSIGHT_CONFIG = INSIGHT_CONFIG;
})(window);
</script>
    <!-- <footer id="footer">
  
  <div class="outer">
    <div id="footer-info" class="inner">
      &copy; 2021 Conor_hua<br>
      powered_by <a href="http://hexo.io/" target="_blank">Hexo</a>
    </div>
  </div>
</footer> -->
<footer id="colophon" class="site-footer" role="contentinfo">
    <div class="site-info">
        <div class="footertext">
            <div class="img-preload">
                <img src="https://cdn.jsdelivr.net/gh/honjun/cdn@1.6/img/other/wordpress-rotating-ball-o.svg">
                <img src="https://cdn.jsdelivr.net/gh/honjun/cdn@1.6/img/other/disqus-preloader.svg">
            </div>
            
            <p>本站总访问量：<a id="allcount"></a></p>
            <p style="color: #666666;">it you can dream it you can do it</p>
            
                <p id="momk" style="font-family: 'Ubuntu', sans-serif;color: #b9b9b9;"></p>
            
        </div>
        <div class="footer-device">
            <p style="font-family: 'Ubuntu', sans-serif;">
 <span style=""> <a 
                         style="color: 	#FF69B4;;text-decoration: underline dotted rgba(0, 0, 0, .1);">Conor_hua</a> <i
             class="iconfont icon-sakura rotating" style="color: #ffc0cb;display:inline-block"></i> Theme <a
             href="https://github.com/xbclub/Hexo-theme-sakura" target="_blank"
             style="color: #FF69B4;;text-decoration: underline dotted rgba(0, 0, 0, .1);">Sakura</a><a
             
             style="color: #b9b9b9;;text-decoration: underline dotted rgba(0, 0, 0, .1);">, Powered by</a><a
             href="https://github.com/hexojs/hexo" target="_blank"
             style="color: #FF69B4;;text-decoration: underline dotted rgba(0, 0, 0, .1);"> Hexo</a>
        </span>
            </p>
        </div>
    </div><!-- .site-info -->
    <!--壁纸切换-->
  <div class="skin-menu no-select" id="mainskin"  style="position: fixed">
    <div class="theme-controls row-container">
        <ul class="menu-list">
            <li id="white-bg"> <i class="fa fa-television" aria-hidden="true"></i></li>
            <li id="sakura-bg"> <i class="iconfont icon-sakura"></i></li>
            <li id="gribs-bg"> <i class="fa fa-slack" aria-hidden="true"></i></li>
            <li id="KAdots-bg"> <i class="iconfont icon-dots"></i></li>
            <li id="totem-bg"> <i class="fa fa-optin-monster" aria-hidden="true"></i></li>
            <li id="pixiv-bg"> <i class="iconfont icon-pixiv"></i></li>
            <li id="bing-bg"> <i class="iconfont icon-bing"></i></li>
            <li id="dark-bg"> <i class="fa fa-moon-o" aria-hidden="true"></i></li>
        </ul>
    </div>
    <div class="font-family-controls row-container">
        <button type="button" class="control-btn-serif selected" data-mode="serif" onclick="mashiro_global.font_control.change_font()">Serif</button>
        <button type="button" class="control-btn-sans-serif" data-mode="sans-serif" onclick="mashiro_global.font_control.change_font()">Sans Serif</button>
    </div>
</div>   
<canvas id="night-mode-cover"></canvas> 
  <div class="changeSkin-gear no-select">
    <div class="keys" id="setbtn"> <span id="open-skinMenu"> 切换壁纸 | SCHEME TOOL 
      &nbsp;<i class="iconfont icon-gear inline-block rotating"></i> </span></div>
</div><!--skin.end-->
</footer>


<!--<script src="https://cdn.jsdelivr.net/gh/xbclub/staticCDN@0.7/js/tocbot.min.js"></script>-->

<script type="text/javascript" src="https://cdn.jsdelivr.net/gh/xbclub/staticCDN@0.8/js/lib.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/clipboard@2/dist/clipboard.min.js"></script>
<script type="text/javascript" src="https://cdn.jsdelivr.net/gh/xbclub/staticCDN@0.8/js/InsightSearch.js"></script>
<script type="text/javascript"
        src="https://cdn.jsdelivr.net/gh/xbclub/staticCDN@0.8/js/jquery.fancybox.min.js"></script>
<script type="text/javascript" src="https://cdn.jsdelivr.net/gh/xbclub/staticCDN@0.8/js/zoom.min.js"></script>

<script type="text/javascript" src="https://cdn.jsdelivr.net/gh/xbclub/staticCDN@1.2/js/sakura-app.js"></script>
    
<script src="https://cdn.jsdelivr.net/gh/xbclub/staticCDN@0.8/js/av-min.js"></script>
<script src='https://cdn.jsdelivr.net/gh/xbclub/staticCDN@0.8/js/Valine.min.js'></script>
<script src="https://cdn.jsdelivr.net/gh/xbclub/staticCDN@0.8/js/botui.js"></script>
<!-- 不蒜子 网页计数器 -->

      
       <script>
  fetch('https://counts.42cloud.cn/api/counts.html')
        .then(response => response.json())
        .then(data => {
              if (document.getElementById("readcount")) {
                document.getElementById("readcount").innerHTML=data.Count;
            }
            if (document.getElementById("allcount")){
                document.getElementById("allcount").innerHTML=data.Allcount;
            }
        })
        .catch(err => console.error(err))
</script>
      
<!-- <script src="https://cdnjs.cloudflare.com/ajax/libs/tocbot/4.4.2/tocbot.min.js"></script> -->
<script type="text/javascript">
    /* <![CDATA[ */
    if (/Android|webOS|iPhone|iPod|BlackBerry/i.test(navigator.userAgent)) {
        var Poi = {
            "pjax": "1",
            "movies": {"url": "https://cdn.jsdelivr.net/gh/honjun/hojun@1.2", "name": "Unbroken.mp4", "live": "close"},
            "windowheight": "fixed",
            "codelamp": "close",
            "ajaxurl": "",
            "order": "asc",
            "formpostion": "bottom"
        };
    } else {
        var Poi = {
            "pjax": "1",
            "movies": {"url": "https://cdn.jsdelivr.net/gh/honjun/hojun@1.2", "name": "Unbroken.mp4", "live": "open"},
            "windowheight": "auto",
            "codelamp": "close",
            "ajaxurl": "",
            "order": "asc",
            "formpostion": "bottom"
        };
    }
    /* ]]> */

</script>
<script>
    $(document).ready(function () {
        if ($(".toc").length > 0 && document.body.clientWidth > 1200) {
            if ($(".pattern-center").length > 0) { //有图的情况
                tocbot.init({
                    // Where to render the table of contents.
                    tocSelector: '.toc', // 放置目录的容器
                    // Where to grab the headings to build the table of contents.
                    contentSelector: '.entry-content', // 正文内容所在
                    // Which headings to grab inside of the contentSelector element.
                    scrollSmooth: true,
                    headingSelector: 'h1, h2, h3, h4, h5', // 需要索引的标题级别
                    headingsOffset: -400,
                    scrollSmoothOffset: -85
                });
            } else {
                tocbot.init({
                    // Where to render the table of contents.
                    tocSelector: '.toc', // 放置目录的容器
                    // Where to grab the headings to build the table of contents.
                    contentSelector: '.entry-content', // 正文内容所在
                    // Which headings to grab inside of the contentSelector element.
                    scrollSmooth: true,
                    headingSelector: 'h1, h2, h3, h4, h5', // 需要索引的标题级别
                    headingsOffset: -85,
                    scrollSmoothOffset: -85
                });
            }
            var offsetTop = $('.toc').offset().top - 95;
            window.onscroll = function () {
                var scrollTop = window.pageYOffset || document.documentElement.scrollTop || document.body.scrollTop;
                if (scrollTop >= offsetTop) {
                    $('.toc').addClass('toc-fixed');
                } else {
                    $('.toc').removeClass('toc-fixed');
                }
            }
        }
    });

</script>
<span style="color: #FF69B4 ;padding-left: 20px;">
    <i class="fa fa-clock-o" aria-hidden="true"></i>
    <span id="time" align="center">载入时间中...</span>

    <script type="text/javascript">
        function NewDate(str) {
            str = str.split('-');
            var date = new Date();
            date.setUTCFullYear(str[0], str[1] - 1, str[2]);
            date.setUTCHours(0, 0, 0, 0);
            return date;
        }

        function momxc() {
            var birthDay = NewDate("2020-7-16");
            var today = new Date();
            var timeold = today.getTime() - birthDay.getTime();
            var sectimeold = timeold / 1000
            var secondsold = Math.floor(sectimeold);
            var msPerDay = 24 * 60 * 60 * 1000;
            var e_daysold = timeold / msPerDay;
            var daysold = Math.floor(e_daysold);
            var e_hrsold = (daysold - e_daysold) * -24;
            var hrsold = Math.floor(e_hrsold);
            var e_minsold = (hrsold - e_hrsold) * -60;
            var minsold = Math.floor((hrsold - e_hrsold) * -60);
            var seconds = Math.floor((minsold - e_minsold) * -60).toString();
            document.getElementById("momk").innerHTML = "本小破站已勉强维持生活" + daysold + "天" + hrsold + "小时" + minsold + "分" + seconds + "秒";
            setTimeout(momxc, 1000);
        }
        
        momxc();
    </script>


</span>


    <div class="openNav no-select" style="height: 50px;">
      <div class="iconflat no-select" style="width: 50px; height: 50px;">
        <div class="icon"></div>
      </div>
      <div class="site-branding search-form-submit">
        <i class="iconfont js-toggle-search iconsearch icon-search"></i>
      </div>
    </div>
  </section>
  <div id="mo-nav" class="">
  <div class="m-avatar">
    <img src="https://cdn.jsdelivr.net/gh/conorhua/asset/ima/xiaomai.jpg">
  </div>
  <p style="text-align: center; color: #333; font-weight: 900; font-family: 'Ubuntu', sans-serif; letter-spacing: 1.5px">Conor_hua</p>
  <p style="text-align: center; word-spacing: 20px;">
    
  </p>
  <ul id="menu-new-1" class="menu">
    
      <li>
        <a href="/">
          <span class="faa-parent animated-hover">
            <i class="fa  fa-fort-awesome faa-shake" aria-hidden="true"></i>
            首页
          </span>
        </a>
        
      </li>
    
      <li>
        <a href="/archives">
          <span class="faa-parent animated-hover">
            <i class="fa  fa-archive faa-shake" aria-hidden="true"></i>
            归档
          </span>
        </a>
        
          <ul class="sub-menu">
            
              <li>
                <a href="/categories/%E6%8A%80%E6%9C%AF/">
                  <i class="fa fa-code" aria-hidden="true"></i>
                  技术
                </a>
              </li>
            
              <li>
                <a href="/categories/%E5%B9%B2%E8%B4%A7/">
                  <i class="fa fa-plug" aria-hidden="true"></i>
                  干货
                </a>
              </li>
            
          </ul>
        
      </li>
    
      <li>
        <a href="javascript:;">
          <span class="faa-parent animated-hover">
            <i class="fa  fa-list-ul faa-vertical" aria-hidden="true"></i>
            清单
          </span>
        </a>
        
          <ul class="sub-menu">
            
              <li>
                <a href="/bangumis/">
                  <i class="fa fa-film faa-vertical" aria-hidden="true"></i>
                  番剧
                </a>
              </li>
            
              <li>
                <a href="/categories/%E6%94%B6%E8%97%8F/">
                  <i class="fa fa-star" aria-hidden="true"></i>
                  收藏
                </a>
              </li>
            
          </ul>
        
      </li>
    
      <li>
        <a href="/tags/">
          <span class="faa-parent animated-hover">
            <i class="fa  fa-tags" aria-hidden="true"></i>
            标签
          </span>
        </a>
        
      </li>
    
      <li>
        <a href="javascript:;">
          <span class="faa-parent animated-hover">
            <i class="fa  fa-leaf faa-wrench" aria-hidden="true"></i>
            关于
          </span>
        </a>
        
          <ul class="sub-menu">
            
              <li>
                <a href="/about/">
                  <i class="fa fa-meetup" aria-hidden="true"></i>
                  我？
                </a>
              </li>
            
              <li>
                <a href="/theme-sakura/">
                  <i class="fa iconfont icon-sakura" aria-hidden="true"></i>
                  主题
                </a>
              </li>
            
          </ul>
        
      </li>
    
      <li>
        <a href="/links/">
          <span class="faa-parent animated-hover">
            <i class="fa  fa-link faa-shake" aria-hidden="true"></i>
            友人帐
          </span>
        </a>
        
      </li>
    
  </ul>
  <p style="text-align: center; font-size: 13px; color: #b9b9b9;">&copy 2019 hexo-sakura</p>
</div>
<button onclick="topFunction()" class="mobile-cd-top" id="moblieGoTop" title="Go to top" style="display: none;"><i class="fa fa-chevron-up" aria-hidden="true"></i></button>
  
</body>
<script src="https://cdn.jsdelivr.net/gh/conorhua/asset/js/noSomeKey.js"></script>
</html>